import 'package:dio/dio.dart';
import 'package:x3_base_core/base_utils/base_utils.dart';
import 'package:x3_base_core/base_utils/base_dio_util.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'package:x3_base_core/base_utils/base_storage_util.dart';
import 'package:x3_base_core/base_models/base_token_model.dart';
import 'package:x3_base_core/base_utils/base_dio_code_util.dart';
import 'package:x3_base_core/base_utils/base_transform_util.dart';
import 'package:x3_base_core/base_enums/base_image_type_enum.dart';
import 'package:x3_base_core/base_enums/base_http_method_enum.dart';
import 'package:x3_base_core/base_models/base_http_result_model.dart';

class BaseDioX2Util {

  /// 调用老X2微服务
  Future<BaseHttpResultModel> fetchX2Microservice( String service, { dynamic params = const {}, bool jumpTokenVerification = false, bool showToast = true, BaseHttpMethodEnum method = BaseHttpMethodEnum.POST } ) async {
    const String requestService = '/mobile/Microservice';
    String requestMethod = BaseTransformUtil.enumToString( method );
    String initRequestService = service.replaceFirst('/', '');
    Map<String, dynamic> requestParams = { "method_id": initRequestService, "jumpTokenVerification": jumpTokenVerification, "content_type": "application/json", "method_type": requestMethod,  ...params };
    BaseHttpResultModel result = await dioUtil.fetch( requestService, params: requestParams, method: BaseHttpMethodEnum.POST, showToast: showToast );
    BaseHttpResultModel initResult = this._initResultData(result, showToast);
    return Future.value(initResult);
  }

  /// 调用老X2业绩宝服务
  Future<BaseHttpResultModel> fetchX3YjbService( String service, { dynamic params = const {}, bool showToast = true, BaseHttpMethodEnum method = BaseHttpMethodEnum.POST } ) async {
    String requestService = '/mobile/api?method=' + service;
    Map<String, dynamic> headers = { "content-type": "application/x-www-form-urlencoded" };
    Map<String, dynamic> requestParams = { ...params };
    BaseHttpResultModel result = await dioUtil.fetch( requestService, headers: headers, params: requestParams, method: BaseHttpMethodEnum.POST, showToast: showToast );
    BaseHttpResultModel initResult = this._initResultData(result, showToast);
    return Future.value(initResult);
  }

  /// 调用老X2普通服务
  Future<BaseHttpResultModel> fetchX2BusinessService( String service, { dynamic params = const {}, bool showToast = true, BaseHttpMethodEnum method = BaseHttpMethodEnum.POST } ) async {
    BaseTokenModel baseToken = BaseStorageUtil.getTokenInfo();
    String requestService = '/x3-service-business/x3/$service';
    Map<String, dynamic> requestParams = { "method": service, "dataJson": { "v1": params }, "languageId": 'zh-cn', 'userId': baseToken.userId };
    return this.fetchX2Microservice( requestService, params: requestParams, jumpTokenVerification: false, showToast: showToast );
  }

  /// 调用XML服务
  Future<BaseHttpResultModel> fetchXMLService( String service, { dynamic params = const {}, bool showToast = true, BaseHttpMethodEnum method = BaseHttpMethodEnum.POST } ) async {
    const String requestService = '/mobile/Method';
    Map<String, dynamic> headers = { "content-type": "application/x-www-form-urlencoded" };
    Map<String, dynamic> requestParams = { ...params, 'method_id': service };
    BaseHttpResultModel result = await dioUtil.fetch( requestService, headers: headers, params: requestParams, method: BaseHttpMethodEnum.POST, showToast: showToast );
    Map<String, dynamic> resultData = BaseDioCodeUtil.decodeMapResult(result.data);
    String status = BaseUtils.getKeyData(resultData, 'status');
    if ( status == "1" ) {
      dynamic objData = BaseUtils.getKeyData( resultData, 'obj' );
      dynamic objDataMap = objData is String ? BaseDioCodeUtil.decodeMapResult( objData ) : objData;
      BaseHttpResultModel objResult = new BaseHttpResultModel( result.code, result.success, objDataMap, null, null );
      return Future.value( objResult );
    }
    String errorMessage = BaseUtils.getKeyData(resultData, 'msg').toString();
    if ( showToast == true ) {
      BaseUtils.showToast(errorMessage);
    }
    BaseHttpResultModel errorResult = new BaseHttpResultModel( result.code, false, errorMessage, null, null );
    return Future.value(errorResult);
  }

  /// 通用上传ByFilePath
  Future<BaseHttpResultModel> fetchUploadFileByFilePath( String filePath, BaseImageTypeEnum typeEnum ) async {
    const String requestService = '/mobile/UploadFile';
    String type = BaseTransformUtil.enumToString( typeEnum ).replaceFirst('X2', '');
    var name = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
    FormData formData = FormData.fromMap({ "file": await MultipartFile.fromFile(filePath, filename: name), 'type': type });
    BaseHttpResultModel result = await dioUtil.fetch(requestService, params: formData, method: BaseHttpMethodEnum.POST);
    Map<String, dynamic> resultData = BaseDioCodeUtil.decodeMapResult(result.data);
    dynamic imageUrl = BaseUtils.getKeyData( resultData, 'obj' );
    BaseHttpResultModel objResult = new BaseHttpResultModel( result.code, result.success, imageUrl, null, null );
    return Future.value( objResult );
  }

  /// 通用上传
  Future<BaseHttpResultModel> fetchUploadFile( MapEntry<String, MultipartFile> file, BaseImageTypeEnum typeEnum ) async {
    const String requestService = '/mobile/UploadFile';
    String type = BaseTransformUtil.enumToString( typeEnum ).replaceFirst('X2', '');
    FormData formData = FormData();
    formData.files.add(file);
    formData.fields.add(MapEntry('type', type));
    BaseHttpResultModel result = await dioUtil.fetch(requestService, params: formData, method: BaseHttpMethodEnum.POST);
    Map<String, dynamic> resultData = BaseDioCodeUtil.decodeMapResult(result.data);
    dynamic imageUrl = BaseUtils.getKeyData( resultData, 'obj' );
    BaseHttpResultModel objResult = new BaseHttpResultModel( result.code, result.success, imageUrl, null, null );
    return Future.value( objResult );
  }

  /// 批量上传
  Future<List<String>> fetchBatchUploadFile( List<AssetEntity> assetEntityList, BaseImageTypeEnum typeEnum ) async {
    List<String> filePaths = await BaseUtils.filterAssetEntity(assetEntityList: assetEntityList, fn: (file, int) => file.path);
    List<MultipartFile> files = filePaths.map((path) {
      String fileName = path.substring(path.lastIndexOf("/") + 1, path.length);
      return MultipartFile.fromFileSync(path, filename: fileName);
    }).toList();
    List<MapEntry<String, MultipartFile>> _filesList = files.map((e) => MapEntry<String, MultipartFile>('file', e)).toList();
    List<String> imageUrls = [];
    for ( int i = 0; i < _filesList.length; i++ ) {
      MapEntry<String, MultipartFile> file = _filesList[i];
      BaseHttpResultModel result = await fetchUploadFile( file, typeEnum );
      imageUrls.add( result.data );
    }
    return Future.value( imageUrls );
  }

  /// 获取错误消息
  String _getErrorMsg( Map<String, dynamic> errorResultData ) {
    dynamic error = BaseUtils.getKeyData(errorResultData, 'error');
    if ( error is String ) return error;
    Map<String, dynamic> errorData = BaseDioCodeUtil.decodeMapResult(error);
    String message = BaseUtils.getKeyData(errorData, 'message').toString();
    String errorMsg = BaseUtils.getKeyData(errorData, 'error').toString();
    return BaseUtils.isNotEmpty(errorMsg) ? errorMsg : message;
  }

  /// 初始化数据
  BaseHttpResultModel _initResultData( BaseHttpResultModel result, bool showToast ) {
    if ( result.success == false ) return new BaseHttpResultModel( result.code, result.success, '', null, null );
    Map<String, dynamic> resultData = BaseDioCodeUtil.decodeMapResult(result.data);
    String success = BaseUtils.getKeyData(resultData, 'success').toString();
    String status = BaseUtils.getKeyData(resultData, 'status').toString();
    BaseHttpResultModel initResult;
    if ( success == 'false' ) {
      dynamic msg = BaseUtils.getKeyData(resultData, 'msg');
      String errorMessage = BaseUtils.isNotEmpty(msg) ? msg : _getErrorMsg(resultData);
      initResult = new BaseHttpResultModel( 500, false, errorMessage, null, null );
    } else if ( status == 'false' ) {
      String errorMsg = BaseUtils.getKeyData(resultData, 'errorMsg').toString();
      initResult = new BaseHttpResultModel( 500, false, errorMsg, null, null );
    } else {
      initResult = new BaseHttpResultModel( result.code, result.success, resultData, null, null );
    }
    return initResult;
  }

}

BaseDioX2Util dioX2Util = new BaseDioX2Util();
